//
// Copyright (c) 2018-2020 Manuel Pöter.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

#ifndef XENIUM_FIXED_SIZE_CIRCULAR_ARRAY_HPP
#define XENIUM_FIXED_SIZE_CIRCULAR_ARRAY_HPP

#include <atomic>
#include <cstdint>
#include <stdexcept>

namespace xenium::detail {
template <class T, std::size_t Capacity>
struct fixed_size_circular_array {
  [[nodiscard]] std::size_t capacity() const { return Capacity; }

  T* get(std::size_t idx, std::memory_order order) { return _items[idx & mask].load(order); }

  void put(std::size_t idx, T* value, std::memory_order order) { _items[idx & mask].store(value, order); }

  [[nodiscard]] constexpr bool can_grow() const { return false; }

  void grow(std::size_t, std::size_t) { throw std::runtime_error("cannot grow fixed_size_circular_array"); }

private:
  static constexpr std::size_t mask = Capacity - 1;
  static_assert((Capacity & mask) == 0, "capacity has to be a power of two");

  std::atomic<T*> _items[Capacity];
};
} // namespace xenium::detail
#endif
